import React, { useEffect, useState } from 'react';
import _ from 'lodash';
import { nanoid } from 'nanoid';
import {
  Button,
  Col,
  Form,
  Input,
  InputNumber,
  Radio,
  Row,
  TreeSelect,
  Cascader,
  Spin,
  message,
} from 'antd';
import DraggableModal from '@/components/DraggableModal';
import DebounceWrapper from '@/components/DebounceWrapper';
import { fetchDistrictList } from '@/services/common';
import { fetchAvailableDictChildList } from '@/services/system/dictionary';
import {
  fetchDepartmentList,
  checkOrganCode,
  addDepartment,
  modifyDepartment,
} from '@/services/system/department';
import { formatTree } from '@/utils/utils';
import styles from './departmentModal.less';

const { Group } = Radio;
const layout = {
  labelCol: { span: 7 },
  wrapperCol: { span: 15 },
};
const corporationDict = [
  { label: '是', value: true },
  { label: '否', value: false },
];
const DebounceButton = DebounceWrapper(Button);

export default ({ visible, options, closeModal, updateList }) => {
  const { id } = options;
  const [form] = Form.useForm();
  const [initialLoading, setInitialLoading] = useState(true);
  const [districtList, setDistrictList] = useState([]);
  const [departmentTypeDict, setDepartmentTypeDict] = useState([]);
  const [organTreeData, setOrganTreeData] = useState([]);
  const [organTreeLoadingId, setOrganTreeLoadingId] = useState('');
  const [actionLoading, setActionLoading] = useState(false);

  // 获取字典数据
  const getDictData = async (dictType) => {
    try {
      const res = await fetchAvailableDictChildList({ dictType });
      return _.isArray(res)
        ? _.filter(
            _.map(res, ({ dictValue, dictLabel }) => ({ value: dictValue, label: dictLabel })),
            ({ value }) => _.isString(value) || _.isNumber(value),
          )
        : [];
    } catch (e) {
      return [];
    }
  };
  // 获取节点列表
  const getOrganTree = async () => {
    try {
      const res = await fetchDepartmentList({ size: -1, current: 1 });
      return _.isArray(res)
        ? formatTree(res, ({ organName, id }) => ({ title: organName, value: id }))
        : [];
    } catch (e) {
      return [];
    }
  };
  // 动态加载省市区节点
  const getDistrictData = async (parentDistrictId = '') => {
    try {
      const { list } = await fetchDistrictList({ parentDistrictId });
      return _.isArray(list)
        ? _.map(
            _.filter(list, ({ districtId }) => !!districtId),
            ({ districtId, name }) => ({ label: name, value: districtId }),
          )
        : [];
    } catch (e) {
      return [];
    }
  };
  const loadDistrictData = (selectedOpts) => {
    const targetOpt = _.last(selectedOpts);
    targetOpt.loading = true;
    getDistrictData(targetOpt.value).then((list) => {
      targetOpt.loading = false;
      if (list.length) {
        targetOpt.children = _.map(list, (item) => ({ ...item, isLeaf: false }));
      } else {
        targetOpt.isLeaf = true;
      }
      setDistrictList([...districtList]);
    });
  };

  // 表单初始化处理
  const formList = [
    {
      name: 'organName',
      label: '机构名称',
      initialValue: '',
      rules: [{ required: true, whitespace: true, message: '请输入机构名称' }],
      component: Input,
      componentProps: {
        maxLength: 24,
        allowClear: true,
        placeholder: '请输入机构名称',
        autoComplete: 'off',
      },
    },
    {
      name: 'organCode',
      label: '机构编码',
      initialValue: '',
      validateTrigger: ['onChange', 'onBlur'],
      rules: [
        { required: true, whitespace: true, message: '请输入机构编码' },
        {
          validateTrigger: 'onBlur',
          validator: async (rule, val) => {
            if (val) {
              try {
                await checkOrganCode(_.assign(id ? { id } : {}, { organCode: val }));
                return Promise.resolve();
              } catch (e) {
                return Promise.reject(new Error(e?.description || '重复校验不通过'));
              }
            }
            return Promise.resolve();
          },
        },
      ],
      component: Input,
      componentProps: {
        maxLength: 24,
        allowClear: true,
        placeholder: '请输入机构编码',
        autoComplete: 'off',
      },
    },
    {
      name: 'parentId',
      label: '机构父节点',
      initialValue: undefined,
      rules: [{ required: true, message: '请选择机构父节点' }],
      component: TreeSelect,
      componentProps: {
        allowClear: true,
        treeData: organTreeData,
        placeholder: '请选择机构父节点',
      },
    },
    {
      name: 'districtItems',
      label: '所在区域',
      initialValue: '',
      rules: [{ required: true, message: '请选择所在区域' }],
      component: Cascader,
      componentProps: {
        allowClear: true,
        options: districtList,
        placeholder: '请选择所在区域',
        loadData: loadDistrictData,
      },
    },
    {
      name: 'formType',
      label: '机构形式',
      initialValue: undefined,
      rules: [{ required: true, message: '请选择机构形式' }],
      component: Group,
      componentProps: {},
      componentChildren: departmentTypeDict.map(({ value, label }) => (
        <Radio key={value} value={value}>
          {label}
        </Radio>
      )),
    },
    {
      name: 'isCorporation',
      label: '是否法人单位',
      initialValue: undefined,
      rules: [{ required: true, message: '请选择是否法人单位' }],
      component: Group,
      componentProps: {},
      componentChildren: corporationDict.map(({ value, label }) => (
        <Radio key={value} value={value}>
          {label}
        </Radio>
      )),
    },
    {
      name: 'phone',
      label: '联系电话',
      initialValue: '',
      rules: [],
      component: Input,
      componentProps: {
        maxLength: 15,
        allowClear: true,
        placeholder: '请输入机构联系电话',
        autoComplete: 'off',
      },
    },
    {
      name: 'email',
      label: '机构邮箱',
      initialValue: '',
      rules: [],
      component: Input,
      componentProps: {
        maxLength: 36,
        allowClear: true,
        placeholder: '请输入机构邮箱',
        autoComplete: 'off',
      },
    },
    {
      name: 'sort',
      label: '机构排序',
      initialValue: 1,
      rules: [
        {
          required: true,
          validator: (field, value) => {
            if (value !== '' && value != null) {
              if (/^\d+$/.test(value)) {
                return Promise.resolve();
              }
              return Promise.reject(new Error('请输入正整数'));
            }
            return Promise.reject(new Error('请输入正整数'));
          },
        },
      ],
      component: InputNumber,
      componentProps: {
        min: 1,
        max: 999,
      },
    },
    {
      name: 'address',
      label: '详细地址',
      initialValue: '',
      rules: [],
      component: Input,
      componentProps: {
        maxLength: 64,
        allowClear: true,
        placeholder: '请输入机构详细地址',
        autoComplete: 'off',
      },
    },
  ];

  // 初始化
  useEffect(() => {
    Promise.all([getDistrictData(), getDictData('form_type')]).then((result) => {
      const [defaultDistrictData, depTypeDict] = result;
      setDistrictList(_.map(defaultDistrictData, (item) => ({ ...item, isLeaf: false })));
      setDepartmentTypeDict(depTypeDict);
      setInitialLoading(false);
    });
  }, []);
  useEffect(() => {
    if (visible) {
      const nextOrganLoadingId = nanoid(12);
      setOrganTreeLoadingId(nextOrganLoadingId);
      if (id) {
        const { provinceId, cityId, districtId, ...restOpts } = options;
        const districtItems =
          provinceId && cityId && districtId ? [provinceId, cityId, districtId] : [];
        const defaultValues = _.assign(_.pick(restOpts, _.map(formList, 'name')), {
          districtItems,
        });
        form.setFieldsValue(defaultValues);
        const districtInitIds = _.slice(districtItems, 0, -1);
        Promise.all([
          getOrganTree(),
          ..._.map(['', ...districtInitIds], (id) => getDistrictData(id)),
        ]).then((result) => {
          const [list, firstDistrictList, ...nodeList] = result;
          let validDataFetch;
          setOrganTreeLoadingId((currentId) => {
            if (currentId === nextOrganLoadingId) {
              validDataFetch = true;
              return '';
            }
            return currentId;
          });
          if (validDataFetch) {
            const rootItem = { title: '顶级机构', value: '0' };
            if (list && list.length) {
              rootItem.children = list;
            }

            // 重组用于回显值的省市区数据项
            const nextDistrictList = _.map(firstDistrictList, (item) => ({
              ...item,
              isLeaf: false,
            }));
            const generateTree = (target, arrList, valList) => {
              const currentList = _.head(arrList);
              if (currentList && currentList.length) {
                const currentVal = _.head(valList);
                const index = _.findIndex(target, ({ value }) => value === currentVal);
                if (index > -1) {
                  target[index].children = currentList;
                  generateTree(currentList, _.slice(arrList, 1), _.slice(valList, 1));
                }
              }
            };
            generateTree(nextDistrictList, nodeList, districtInitIds);

            setOrganTreeData([rootItem]);
            setDistrictList(nextDistrictList);
          }
        });
        return;
      }
      getOrganTree().then((list) => {
        let validDataFetch;
        setOrganTreeLoadingId((currentId) => {
          if (currentId === nextOrganLoadingId) {
            validDataFetch = true;
            return '';
          }
          return currentId;
        });
        if (validDataFetch) {
          const rootItem = { title: '顶级机构', value: '0' };
          if (list && list.length) {
            rootItem.children = list;
          }
          setOrganTreeData([rootItem]);
        }
      });
      return;
    }
    form.resetFields();
    setOrganTreeData([]);
    setOrganTreeLoadingId('');
  }, [visible]);

  // 取消
  const handleCancel = () => {
    if (!actionLoading) {
      closeModal();
    }
  };
  // 提交
  const handleConfirm = () => {
    setActionLoading(true);
    form
      .validateFields()
      .then((values) => {
        const { districtItems, ...restValues } = values;
        const [provinceId, cityId, districtId] = districtItems || [];
        const params = _.assign(id ? { id } : {}, restValues, { provinceId, cityId, districtId });
        // console.log('提交', params);
        const confirmAction = params.id ? modifyDepartment : addDepartment;
        confirmAction(params)
          .then(() => {
            closeModal();
            setActionLoading(false);
            updateList && updateList();
            message.success(`机构${params.id ? '修改' : '新增'}成功`);
          })
          .catch(() => {
            setActionLoading(false);
          });
      })
      .catch(() => {
        setActionLoading(false);
      });
  };

  return (
    <DraggableModal
      width={780}
      visible={visible}
      title={`机构${id ? '编辑' : '添加'}`}
      onCancel={handleCancel}
      footer={[
        <DebounceButton key="cancel" disabled={actionLoading} onClick={closeModal}>
          取消
        </DebounceButton>,
        <DebounceButton
          key="confirm"
          type="primary"
          loading={actionLoading}
          onClick={handleConfirm}
        >
          提交
        </DebounceButton>,
      ]}
    >
      <Spin spinning={initialLoading || !!organTreeLoadingId} tip={'初始化..'}>
        <div className={styles.departmentFormContainer}>
          <Form {...layout} form={form} name="department-form">
            <Row>
              {formList.map((item, index) => (
                <Col key={item.name} md={12} xs={24}>
                  <Form.Item
                    {..._.pick(item, [
                      'name',
                      'label',
                      'rules',
                      'tooltip',
                      'initialValue',
                      'validateTrigger',
                      'labelCol',
                      'wrapperCol',
                    ])}
                  >
                    {item.component
                      ? React.createElement(
                          item.component,
                          { ...item.componentProps },
                          item.componentChildren,
                        )
                      : null}
                  </Form.Item>
                </Col>
              ))}
            </Row>
          </Form>
        </div>
      </Spin>
    </DraggableModal>
  );
};
